package gui;

import javax.swing.text.*;
import java.awt.*;

/**
 * @author dotekien
 *         Date: Apr 13, 2006
 *         Time: 10:17:56 PM
 */
public class SameHighlightPainter extends LayeredHighlighter.LayerPainter
        implements Highlighter.HighlightPainter {
    protected Color color;

    public SameHighlightPainter(Color c) {
        color = c;
    }

    public Color getColor() {
        return color;
    }

    public Shape paintLayer(Graphics g, int offs0, int offs1,
                            Shape bounds, JTextComponent c, View view) {

        Color color = getColor();

        if (offs0 == view.getStartOffset() &&
                offs1 == view.getEndOffset()) {
            // Contained in view, can just use bounds.
            Rectangle alloc;
            if (bounds instanceof Rectangle) {
                alloc = (Rectangle) bounds;
            } else {
                alloc = bounds.getBounds();
            }

            highlight(g, color, alloc);

            return alloc;
        } else {
            // Should only render part of View.
            try {
                // --- determine locations ---
                Shape shape = view.modelToView(offs0, Position.Bias.Forward,
                        offs1, Position.Bias.Backward,
                        bounds);
                Rectangle r = shape instanceof Rectangle ? (Rectangle) shape : shape.getBounds();
                highlight(g, color, r);
                return r;
            } catch (BadLocationException e) {
                // can't render
            }
        }
        // Only if exception
        return null;
    }

    private static void highlight(final Graphics g, final Color color, final Rectangle r) {
        Graphics2D g2D = (Graphics2D) g;
        Composite originalComposite = g2D.getComposite();
        g2D.setPaint(color);
        g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        g.fillRect(r.x, r.y, r.width, r.height);
        g2D.setComposite(originalComposite);
    }

    private void paintLine(Graphics2D g2D, Rectangle r, int x2) {

        Composite originalComposite = g2D.getComposite();
        g2D.setPaint(color);
        g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
        g2D.fillRect(r.x, r.y, x2 - r.x, r.y + r.height);
        g2D.setComposite(originalComposite);
    }

    public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {

        Rectangle r0, r1, rbounds = bounds.getBounds();
        int xmax = rbounds.x + rbounds.width; // x-coordinate of right edge
        try {  // Convert positions to pixel coordinates.
            r0 = c.modelToView(p0);
            r1 = c.modelToView(p1);
        } catch (BadLocationException ex) {
            return;
        }

        if (r0 == null || r1 == null) return;

        Graphics2D g2D = (Graphics2D) g;
        // Special case if p0 and p1 are on the same line
        if (r0.y == r1.y) {
            paintLine(g2D, r0, r1.x);
        } else {
            // First line, from p1 to end-of-line
            paintLine(g2D, r0, xmax);
            r0.y += r0.height;   // Move r0 to next line.
            r0.x = rbounds.x; // Move r0 to left edge.

            while (r0.y < r1.y) {
                paintLine(g2D, r0, xmax);
                r0.y += r0.height; // Move r0 to next line.
            }
            // Last line, from beginning-of-line to p1
            paintLine(g2D, r0, r1.x);
        }
    }
}
